聊一聊matplotlib绘图时自定义坐标轴标签顺序
关注可以叫我才哥,学习分享数据之美
我们的第70篇原创
作者:Ryoko
编辑:才哥
☆
大家好,我是才哥。
今天我们聊一个matplotlib
绘图问题,就是关于如何对坐标轴标签(常见的x轴标签)按照自定义的顺序走。
话说这是在昨天,发生在咱们交流群的故事:一位同学提问 “matplotlib
画柱状图时,横坐标是从表格中指定列获取的,如何设置横坐标的顺序呢?”
原始数据结构如下图所示,需要对学历分组求平均工资后画柱状图,顺序应为按学历由低到高,即 ['大专', '本科', '硕士', '博士']
。
看到案例数据,感觉先分组求均值,如何再进行绘图就行了。但是似乎直接这样得到的可视化图不满足需求,坐标轴标签顺序与期望的不一致。怎么回事呢?
1. 直接作图
我们先看一下分组求均值后结果数据的情况:
grp = df.groupby('学历要求')['平均工资'].mean().reset_index()
grp
我们发现,在分组后学历要求分组里的排序是博士、大专、本科和硕士,与我们期望的['大专', '本科', '硕士', '博士']
其实不一样。
这种情况下直接作图结果如下:
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = grp['学历要求']
y = grp['平均工资']
plt.bar(x, y)
plt.show()
很明显,这个图并非我们期望的,那么如何按照我们期望的x轴坐标轴标签顺序作图呢?
以下,我们将介绍多种方式,希望能供大家参考~
2. 绘图时设置坐标轴标签顺序
以下方法来自才哥,简单直接的处理:
plt.bar([3, 0, 1, 2], grp['平均工资'], tick_label=grp['学历要求'])
在以上作图代码中,我们简单讲解下三个参数作用:
第1个参数[3,0,1,2]含义可以理解为将原图里第0个数据也就是博士对应数据放在第3个位置,将1-3个数据放到0-2位置,从而可以得到我们需要的结果; 第2个参数 y = grp['平均工资']
就是柱状图高度数据,也就是会根据第1个参数设置的位置进行显示;第3个参数 tick_label
就是设置坐标轴标签,这里就是grp['学历要求']
。
核心是第1个参数,可以简单理解为它就是你期望的坐标轴标签顺序。
如果遇到标签较多的情况,我们已知期望顺序列表但是人均排序似乎有点累,这里可以用列表位置索引
帮我们快速找到期望顺序。
# 期望标签列表顺序(变量,自己决定顺序)
index_list = ['大专','本科','硕士','博士']
# 期望顺序列表
index = [index_list.index(x) for x in grp.学历要求.to_list()]
index
[3, 0, 1, 2]
3. 绘图前先对x,y数据进行排序
当然,除了上述在绘图时对坐标轴标签指定顺序外,我们还可以在绘图前将绘图核心参数x,y
的值进行指定排序。
# Series数据
grp = df.groupby('学历要求')['平均工资'].mean()
grp
# 指定期望的标签列表顺序
x = ['大专', '本科', '硕士', '博士']
# 根据x 获取对应 y值
y = [grp[label] for label in x]
plt.bar(x, y)
由于忘记了 matplotlib
和 pandas
之间有着很好的兼容性,笔者一开始打算先得到需求顺序的 x = ['大专', '本科', '硕士', '博士']
和 y = [ 具体的值 ]
再通过 plt.bar(x, y)
制图,因此在数据整理上跑偏了,比如:
y = [grp.at[label] for label in x]
下面分享一下笔者走的歪路
4. 自定义文本排序
计算机系统中存在一些默认顺序,比如数字顺序 0123456
,字母顺序 abcdefg
,还有 ASCII 码
表顺序等,但对于中文习惯的顺序,比如学历,可能就需要自己制定了。那让我们专注排序本身,先来看看分组后的数据:
x = grp['学历要求']
和 y = grp['平均工资']
分别得到两个 Series 对象。那么应该如何将它们绑定在一起,根据 x 按照指定的 order_x = ['大专', '本科', '硕士', '博士']
排序呢?
4.1. 打包排序
我们可以通过 zip()
函数将其打包使之成为一个整体,然后通过列表生成式,得到修改顺序后的 y 轴值列表 order_y
,将 order_x
和 order_y
传入制图即可。
order_y = [t[1] for i in order_x for t in list(zip(x, y)) if i == t[0]]
其中:
list(zip(x, y)) 的打印结果为: [('博士', 20.0), ('大专', 5.25), ('本科', 11.0), ('硕士', 15.33)]
;列表生成式重新取出的元祖列表为: [('大专', 5.25), ('本科', 11.0), ('硕士', 15.33), ('博士', 20.0)]
;order_y 为: [5.25, 11.0, 15.33, 20.0]
。
4.2. 利用 pandas 重设索引排序
整体代码:
grp = df.groupby('学历要求')['平均工资'].mean().reset_index()
df_map = pd.DataFrame({'学历要求': ['大专', '本科', '硕士', '博士']}).reset_index().set_index('学历要求')
grp['order'] = grp['学历要求'].map(df_map['index'])
grp.sort_values('order', inplace=True)
x = grp['学历要求']
y = grp['平均工资']
首先制作了一个 df_map
,相当于是排序对照表,将索引作为新的顺序列。
将上面的顺序列,按照原 grp
的学历要求列,映射添加到新的 order 列 。
再按照 order
列排序即可。
4.3. 利用 CategoricalDtype 自定义顺序
CategoricalDtype
是 pandas 中一种用于处理【类别】的数据类型,可以指定类别是否有序。
我们通过这个方法创建了一个有序 “类别类”,并修改学历要求列的数据类型为此类,此时各类学历文本便具有了其默认顺序,之后便可以对其直接排序。
from pandas.api.types import CategoricalDtype
grp = df.groupby('学历要求')['平均工资'].mean().reset_index()
cat_order = CategoricalDtype(['大专', '本科', '硕士', '博士'], ordered=True)
grp['学历要求'] = grp['学历要求'].astype(cat_order)
grp['学历要求']
我们可以看到 类别下有排序属性'大专' < '本科' < '硕士' < '博士'
,然后排序作图即可。
grp.sort_values('学历要求', inplace=True)
x = grp['学历要求']
y = grp['平均工资']
plt.bar(x,y)
以上就是本次全部内容,希望对大家在进行自定义坐标轴排序的时候有帮助。
题外话:其实关于 CategoricalDtype
,还有很多非常重要的作用,这个留给大家思考吧,后续我们可以继续讨论!
-->推荐阅读<--
今年五一北京到三亚的机票1万多??用Python扒一扒三亚都有啥子好玩嘛!! 浅谈游戏运营中LTV的计算 用一行Python代码实现按字符串内数字大小排列字符串顺序 Python爬虫 | 手把手教你扒一扒贝壳网成交房源数据 [数据分析] 使用Python简单玩玩RFM用户价值模型 关于移动游戏运营数据指标,这里有一份简单说明,请查收 邻近模糊匹配?你可能不知道的pandas骚操作,确实很好用! 再推荐几个好用的pandas函数,继续加快你数据处理的速度
扫码添加作者好友,一起组队学习
微信号
dxaw142857
微信公众号
可以叫我才哥
分享、在看与点赞
爱你一万年~